'''
Created on Nov 12, 2010

@author: dexen
'''

import copy

from dexen.system.common.base import Individual


class IndMgr(object):
    def __init__(self):
        self.inds = {}
        self.cur_id = 1
        self.cur_time = 1 # refers to action id
    
    def set_cur_time(self, act_id):
        self.cur_time = act_id
    
    def add_ind(self, ind):
        #print "adding the following ind:\n"
        #print ind.__repr__()
        assert isinstance(ind, Individual)
        ind._set_id(self.cur_id)
        ind._set_act_time(self.cur_time) # It is newly born
        self.inds[self.cur_id] = ind
        self.cur_id += 1
        return ind
    
    def update_ind(self, ind):
        assert isinstance(ind, Individual)
        target_ind = self.inds[ind.__id__]
        assert isinstance(target_ind, Individual)
        for name in ind.__modified__.keys():
            setattr(target_ind, name, getattr(ind, name))
        
        # Writing the archived data
        target_ind.__archived__ = ind._get_archived()        
        target_ind._reset_modified()
        return target_ind
    
    def reactivate_ind(self, id):
        ind = self.inds[id]
        assert isinstance(ind, Individual)
        ind._set_inact_time(None)
    
    def deactivate_ind(self, id):
        ind = self.inds[id]
        assert isinstance(ind, Individual)
        ind._set_inact_time(self.cur_time)
        
    def set_ind(self, ind):
        assert isinstance(ind, Individual)
        if ind._is_new():
            ind = self.add_ind(ind)
        else: 
            ind = self.update_ind(ind)  
        return ind
    
    def get_ind(self, id):
        ind = copy.deepcopy(self.inds[id])
        assert isinstance(ind, Individual)
        ind._reset_modified()
        return ind

    def strip_ind_archive(self, id):
        ind = self.inds[id]
        assert isinstance(ind, Individual)
        ind._strip_archived()
              
    def num_inds(self):
        return self.cur_id - 1
    
    def __repr__(self):
        out = "------------- IndMgr --------------\n"
        out += "Pop size: {0}\n".format(self.num_inds())
        out += "-----------------------------------\n"
        return out 

#===============================================================================
# Unit Testing
#===============================================================================
import unittest

class TestIndMgr(unittest.TestCase):
    def setUp(self):
        self.ind_mgr = IndMgr()
    
    def tearDown(self):
        pass

    def _set_inds(self, num):
        for _ in range(num):
            self.ind_mgr.set_ind(Individual())

    def test_set_ind(self):
        ind = Individual()
        ind.name = "Cihat"
        self.ind_mgr.set_ind(ind)
        self.assertTrue(self.ind_mgr.num_inds() == 1)
        ind_copy = self.ind_mgr.get_ind(1)
        self.assertTrue(ind_copy.name == ind.name and id(ind) != id(ind_copy))
        assert isinstance(ind_copy, Individual)
        self.assertTrue(ind_copy._get_id() == 1)
        
    def test_get_evaluated_inds(self):
        self._set_inds(10)
        self.assertTrue(self.ind_mgr.num_inds() == 10)
        
    
def main():
    unittest.main()
    
if __name__ == "__main__":
    main()
